package Util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Logger;

/**
 * @author GuoZeXin
 * @version 2.0.1
 * 
 * @created 2014.12.9
 * @latest 2014.12.11
 */
public class CryptoUtil {

	private static Logger logger = (Logger) LogManager.getLogger(CryptoUtil.class.getName());
	private static Crypto2 crypto2 = new Crypto2();
	private static boolean flag;

	/**
	 * 添加flag静态变量，作为文件加密解密成功与否的标志。
	 * getEncode(File),getDecode(File),需先判断是否加密解密成功。即调用getFlag()
	 * 
	 * @author GuoZeXin
	 * @version 2.0.1
	 * 
	 * @created 2014.12.10
	 * @latest 2014.12.10
	 * @return
	 */
	public static boolean getFlag(){
		return flag;
	}

	/**
	 * 把字符串的秘钥byte包装成String类型返回
	 * @author GuoZeXin
	 * @version 2.0.1
	 * 
	 * @created 2014.12.11
	 * @latest 2014.12.11
	 * 
	 * @param b
	 * @return
	 */
	public static String byteToString(byte b[]){
		StringBuffer strBuffer = new StringBuffer();
		for(int i = 0;i < b.length;i++){
			strBuffer.append(b[i] + "@");
		}
		return strBuffer.toString();
	}

	/**
	 * 把字符串String类型的秘钥解析成byte数组返回
	 * @author GuoZeXin
	 * @version 2.0.1
	 * 
	 * @created 2014.12.11
	 * @latest 2014.12.11
	 * 
	 * @param str
	 * @return
	 */
	public static byte[] stringToByte(String str){
		String items[] = str.split("@");
		int len = items.length;
		byte b[] = new byte[len];
		for(int i = 0;i < len;i++){
			b[i] = Byte.valueOf(items[i]);
		}
		return b;
	}

	/**
	 * 把byte类型的字符串加到是8的倍数再返回字节数组，最后一段不够8位补空格
	 * @author GuoZeXin
	 * @version 2.0.1
	 * 
	 * @created 2014.12.11
	 * @latest 2014.12.11
	 * 
	 * @param str
	 * @return
	 */
	public static byte[] getBytes(byte[] b){
		int len = b.length,newLen = (len + 7) / 8 * 8;
		byte newB[] = new byte[newLen];
		for(int i = 0;i < newLen;i++){
			if(i < len)
				newB[i] = b[i];
			else
				newB[i] = ' ';
		}

		return newB;
	}

	/**
	 * 加密String,返回密文。
	 * @author GuoZeXin
	 * @version 2.0.1
	 * 
	 * @created 2014.12.9
	 * @latest 2014.12.11
	 * 
	 * @param origin
	 * @return
	 */
	public static byte[] getEncode(byte[] origin){
		if(origin == null){
			logger.info("命令为空值，拒绝加密");
			return null;
		}
		logger.info("加密命令");
		byte[] encrypt = null;
		byte b[] = getBytes(origin);
		//System.out.println(b.length);
		encrypt = crypto2.encrypt(b);
		//printBytes(encrypt);
		//logger.info("命令加密为：" + new String(encrypt));
		return encrypt;
	}

	private static void printBytes(byte[] b){
		System.out.println("byte[] length:" + b.length);
		for(int i = 0; i < b.length; i++){
			System.out.print(b[i]+" ");
		}
		System.out.println("end");
	}
	/**
	 * 解密String,返回明文。
	 * @author GuoZeXin
	 * @version 2.0.1
	 * 
	 * @created 2014.12.9
	 * @latest 2014.12.9
	 * 
	 * @param encrypt
	 * @return
	 */
	public static String getDecode(String encrypt){
		String origin = null;
		origin = new String(crypto2.decrypt(stringToByte(encrypt)));
		return origin;
	}

	/**
	 * 加密file,变成密文。加密成功则删除原文件，再把临时文件改名为原文件名，再返回，加密失败则返回原来明文File
	 * @author GuoZeXin
	 * @version 2.0.1
	 * 
	 * @created 2014.12.9
	 * @latest 2014.12.11
	 * 
	 * @param originFile 待加密的file
	 * @return 返回加密的file
	 */
	public static File getEncode(File originFile){
		FileInputStream fin = null;
		flag = true;
		try {
			fin = new FileInputStream(originFile);
		} catch (FileNotFoundException e) {
			logger.warn("明文文件未找到");
			flag = false;
		}
		File encryptFile = new File(originFile.getParent() + "/enc_" + originFile.getName());
		FileOutputStream fout = null;
		try {
			fout = new FileOutputStream(encryptFile);
		} catch (FileNotFoundException e1) {
			logger.warn("密文临时文件未找到");
			flag = false;
		}
		byte origin[] = new byte[1024],encrypt[] = new byte[1024];
		logger.info("开始加密");
		try {
			while(fin.read(origin) > 0){
				encrypt = crypto2.encrypt(origin);
				fout.write(encrypt);
			}
		} catch (IOException e) {
			flag = false;
			logger.warn("读取明文出错");
		}
		if(fin != null)
			try {
				fin.close();
			} catch (IOException e) {
				flag = false;
				logger.warn("关闭明文失败");
			}
		if(fout != null){
			try {
				fout.close();
			} catch (IOException e) {
				logger.warn("密文文件关闭出错");
				flag = false;
			}
		}
		if(flag){
			originFile.delete();
			encryptFile.renameTo(originFile);
			logger.info("加密成功");
			return encryptFile;
		}
		else{
			logger.info("加密失败");
			return originFile;
		}

	}
	/**
	 * 解密，返回明文，并删除原来文件。加密成功则删除密文文件，再把临时文件改名为密文文件名，再返回，加密失败则返回原来密文File
	 * 
	 * @author GuoZeXin
	 * @version 2.0.1
	 * 
	 * @created 2014.12.10
	 * @latest 2014.12.11
	 * 
	 * @param encryptFile
	 * @return
	 */
	public static File getDecode(File encryptFile){
		FileInputStream fin = null;
		flag = true;
		try {
			fin = new FileInputStream(encryptFile);
		} catch (FileNotFoundException e) {
			logger.warn("密文文件未找到");
			flag = false;
		}
		File originFile = new File(encryptFile.getParent() + "/dec_" + encryptFile.getName());
		FileOutputStream fout = null;
		try {
			fout = new FileOutputStream(originFile);
		} catch (FileNotFoundException e1) {
			logger.warn("明文临时文件未找到");
			flag = false;
		}
		byte origin[] = new byte[1024],encrypt[] = new byte[1024];
		logger.info("开始解密文件" + encryptFile.getName());
		//boolean f = false;
		try {
			while(fin.read(encrypt) > 0){
				origin = crypto2.decrypt(encrypt);
				/*if(!f){
				printBytes(origin);
				f = true;
				}*/
				fout.write(origin);
			}
		} catch (IOException e) {
			flag = false;
			logger.warn("读取密文文件出错");
		}
		if(fin != null)
			try {
				fin.close();
			} catch (IOException e) {
				flag = false;
				logger.warn("关闭密文文件失败");
			}
		if(fout != null){
			try {
				fout.close();
			} catch (IOException e) {
				logger.warn("关闭明文文件出错");
				flag = false;
			}
		}
		if(flag){
			encryptFile.delete();
			originFile.renameTo(encryptFile);
			logger.info("密文文件：" + encryptFile.exists() + " " + "临时文件：" + originFile.exists());
			logger.info(encryptFile.getName()+" 解密文件成功");
			
		}
		else{
			logger.info(encryptFile.getName()+" 解密文件失败");
			
		}
		return encryptFile;
	}

}

